// Copyright (c) Microsoft Corporation.  All rights reserved.

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;

namespace Microsoft.WindowsAPICodePack.DirectX.DirectXUtilities
{
    [StructLayout(LayoutKind.Sequential)]
    public struct Vector2F
    {
        public float x;
        public float y;
        public Vector2F(float x, float y)
        {
            this.x = x;
            this.y = y;
        }

        public float[] ToArray()
        {
            return new float[] { x, y };
        }
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct Vector3F
    {
        public float x;
        public float y;
        public float z;

        public Vector3F(float x, float y, float z)
        {
            this.x = x;
            this.y = y;
            this.z = z;
        }

        public Vector3F(float[] vector)
        {
            this.x = vector[0];
            this.y = vector[1];
            this.z = vector[2];
        }

        public float[] ToArray()
        {
            return new float[] { x, y, z };
        }

        public Vector3F Normalize()
        {
            float length = (float)Math.Sqrt(x * x + y * y + z * z);
            if (length == 0)
                return new Vector3F(0, 0, 0);
            else
                return new Vector3F(x / length, y / length, z / length);
        }

        public void NormalizeInPlace()
        {
            float length = (float)Math.Sqrt(x * x + y * y + z * z);
            if (length == 0)
            {
                x = 0;
                y = 0;
                z = 0;
            }
            else
            {
                x /= length;
                y /= length;
                z /= length;
            }
        }

        public static float Dot(Vector3F a, Vector3F b)
        {
            return a.x * b.x + a.y * b.y + a.z * b.z;
        }

        public static Vector3F Cross(Vector3F a, Vector3F b)
        {
            return new Vector3F(
                a.y * b.z - a.z * b.y,
                a.z * b.x - a.x * b.z,
                a.x * b.y - a.y * b.x);
        }

        public static Vector3F operator +(Vector3F a, Vector3F b)
        {
            return new Vector3F(a.x + b.x, a.y + b.y, a.z + b.z);
        }

        public static Vector3F operator -(Vector3F a, Vector3F b)
        {
            return new Vector3F(a.x - b.x, a.y - b.y, a.z - b.z);
        }
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct Vector4F
    {
        public float x;
        public float y;
        public float z;
        public float w;

        public Vector4F(float x, float y, float z, float w)
        {
            this.x = x;
            this.y = y;
            this.z = z;
            this.w = w;
        }

        public Vector4F( float[] xyzw )
        {
            if( xyzw.Length != 4 )
                throw new ArgumentException( "xyzw not properly sized." );
            this.x = xyzw[ 0 ];
            this.y = xyzw[ 1 ];
            this.z = xyzw[ 2 ];
            this.w = xyzw[ 3 ];
        }

        public float[ ] ToArray( )
        {
            return new float[] { x, y, z, w };
        }
    }
}
